﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.ComponentModel;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;
using System.Web.UI;
using TST.SharePoint.Shared;
using TST.WebParts.Shared.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint.Utilities;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using System.Xml.Xsl;
using System.Web;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

namespace TST.WebParts
{
    [ViewStateModeById]
    public class ListItemFilter : WebPart, IWebEditable, Microsoft.SharePoint.WebPartPages.ITransformableFilterValues, Microsoft.SharePoint.WebPartPages.IDefaultFilterValue
    {
        private string[] fontSizes = new string[] { "22", "18", "14", "12", "10", "9" };
        Microsoft.SharePoint.WebPartPages.IFilterValues _filterValues;
        private List<string> _distinctValues;
        public const string EMPTYITEMVALUE = "-1";
        private const string SHOWALLITEM = "__all__";
        private const string SHOWALLITEMTEXT = "Show all";
        ListControl _listControl = null;
        private SPList _list;
        private string _controlCssClass;
        private Exception _exception;
        private List<string> _debugLines;
        private int _origDisplayMode;
        private bool _origDisplayWebPartTitle;
        private bool _forceListReload;
        private string _origListUrl;
        private string _origDisplayField;
        private string _origValueField;
        private bool _origSelectDistinct;
        private string _origDropDownFirstItem;
        private Microsoft.SharePoint.WebPartPages.IDefaultFilterValue _defaultValueProvider;
        private uint _origItemLimit;

        private string PreviousFilterAsText
        {
            get
            {
                if (ViewState["PreviousFilterAsText"] != null)
                {
                    return (string)ViewState["PreviousFilterAsText"];
                }
                return null;
            }
            set
            {
                ViewState["PreviousFilterAsText"] = value;
            }
        }

        private TagList CurrentTagList
        {
            get
            {
                if (ViewState["CurrentTagList"] != null)
                {
                    return (TagList)ViewState["CurrentTagList"];
                }
                return null;
            }
            set
            {
                ViewState["CurrentTagList"] = value;
            }
        }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string ListUrl { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string DisplayField { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string ControlCssClass
        {
            get
            {
                if (string.IsNullOrEmpty(_controlCssClass))
                {
                    return "ms-vb2";
                }
                else
                {
                    return _controlCssClass;
                }
            }
            set
            {
                _controlCssClass = value;
            }
        }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string ValueField { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public int DisplayMode { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public String DropDownFirstItem { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public bool DisplayWebPartTitle { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public bool ShowAllInTagCloud { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public uint ItemLimit { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public Boolean HideSeachButton { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public bool SelectDistinct { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public bool Debug { get; set; }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string XsltStyleSheet { get; set; }
        
        private bool HasFilter
        {
            get
            {
                if (ViewState["HasListItemFilter"] != null)
                {
                    return (bool)ViewState["HasListItemFilter"];
                }
                return false;
            }
            set
            {
                ViewState["HasListItemFilter"] = value;
            }
        }

        private List<string> DebugLines
        {
            get
            {
                if (_debugLines == null)
                {
                    _debugLines = new List<string>();
                }
                return _debugLines;
            }
        }

        public string ResourcePath
        {
            get
            {
                SPWeb currentWeb = SPContext.Current.Web;
                Type currentType = this.GetType();
                string classResourcePath = Microsoft.SharePoint.WebPartPages.SPWebPartManager.GetClassResourcePath(currentWeb, currentType);
                classResourcePath = GetRelativeResourcePath(classResourcePath);
                classResourcePath = Page.Server.MapPath(classResourcePath);
                return classResourcePath;
            }
        }

        private static string GetRelativeResourcePath(string classResourcePath)
        {
            string resources = classResourcePath;
            int p = resources.ToLower().IndexOf("wpresources");
            string s = resources.Substring(1, p);
            p = s.LastIndexOf("/") + 1;
            if (p > 1)
            {
                resources = resources.Substring(p, resources.Length - p);
            }
            return resources + "/";
        }

        public ListItemFilter()
        {
            this.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None;
            _distinctValues = new List<string>();
            DisplayWebPartTitle = true;
        }

        protected override void OnInit(EventArgs e)
        {
            // Initialize controlstate variable with Display Mode
            // Register this control as requiring controlstate
            _origDisplayMode = DisplayMode;
            Page.RegisterRequiresControlState(this);
            
            base.OnInit(e);

            // Initialize variables to track when webpart edits
            // indicate the list should be repopulated
            _forceListReload = false;
            _origListUrl = ListUrl;
            _origDisplayField = DisplayField;
            _origValueField = ValueField;
            _origSelectDistinct = SelectDistinct;
            _origDisplayWebPartTitle = DisplayWebPartTitle;
            _origDropDownFirstItem = DropDownFirstItem;
            _origItemLimit = ItemLimit;
        }

        // Load controlstate for inherited controls & this control
        protected override void LoadControlState(object savedState)
        {
            object[] stateLastRequest = (object[])savedState;
            object baseState = stateLastRequest[0];
            base.LoadControlState(baseState);
            this._origDisplayMode = (int)stateLastRequest[1];
            this._origDisplayWebPartTitle = (bool)stateLastRequest[2];
            this._origItemLimit = (uint)stateLastRequest[3];
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            if (ItemList==null)
                return;
            if (DisplayWebPartTitle)
            {
                Label label = new Label();
                label.CssClass = ControlCssClass;
                label.Text = this.Title;
                label.Font.Bold = true;
                Controls.Add(label);
                Controls.Add(new LiteralControl("<br />"));
            }
            switch (_origDisplayMode)
            {
                case 2:
                    _listControl = new CheckBoxList();
                    _listControl.AutoPostBack = false;
                    _listControl.Width = 200;
                    _listControl.CssClass = ControlCssClass;
                    Controls.Add(_listControl);
                    if (!HideSeachButton)
                    {
                        Button search = new Button();
                        search.Text = "Search";
                        search.CssClass = ControlCssClass;
                        search.Click += new EventHandler(search_Click);
                        Controls.Add(search);
                    }
                    break;
                case 1:
                    _listControl = new RadioButtonList();
                    _listControl.AutoPostBack = true;
                    _listControl.Width = 200;
                    _listControl.CssClass = ControlCssClass;
                    Controls.Add(_listControl);
                    break;
                case 0:
                    _listControl = new DropDownList();
                    _listControl.AutoPostBack = true;
                    _listControl.Width = 200;
                    _listControl.CssClass = ControlCssClass;
                    Controls.Add(_listControl);
                    break;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            // If DisplayMode/DisplayWebPartTitle changed in WebPartEditor, update
            // controlstate variable, clear existing controls,
            // rebuild the controls
            if (_origDisplayMode != DisplayMode || _origDisplayWebPartTitle != DisplayWebPartTitle || _origItemLimit!=ItemLimit)
            {
                _origDisplayMode = DisplayMode;
                _origDisplayWebPartTitle = DisplayWebPartTitle;
                _origItemLimit = ItemLimit;
                _listControl = null;
                this.Controls.Clear();
                this.CreateChildControls();
                ForceReload();
            }
            else
            {
                // Populate The List When The Fields Defining
                // The List Contents Have Been Modified
                if ((_origListUrl != ListUrl) || (_origDisplayField != DisplayField)
                    || (_origValueField != ValueField) || (_origSelectDistinct != SelectDistinct)
                    || (_origDropDownFirstItem != DropDownFirstItem))
                    ForceReload();
            }

            if ((!Page.IsPostBack || _forceListReload))
            {
                // save the filter
                PreviousFilterAsText = SaveFilter();

                if (_listControl != null)
                {
                    // Using a list control.
                    PopulateList();
                    ListItemHelper.SortListItems(_listControl.Items, false);
                }
                else
                {
                    // Tagcloud or XSLT.
                    CurrentTagList = PopulateTagList();
                }
            }

            base.OnPreRender(e);
        }

        private void ForceReload()
        {
            _forceListReload = true;
            _list = null;
        }

        // save controlstate for inherited controls & this control 
        protected override object SaveControlState()
        {
            object basestate = base.SaveControlState();
            _origDisplayMode = DisplayMode;
            _origDisplayWebPartTitle = DisplayWebPartTitle;
            _origItemLimit = ItemLimit;
            object thisstate = new object[] { basestate, this._origDisplayMode, this._origDisplayWebPartTitle, this._origItemLimit };
            return thisstate;
        }

        private void search_Click(object sender, EventArgs e)
        {
        }

        private void ResetList()
        {
            if (_listControl == null)
                return;
            _listControl.Items.Clear();
            if (_listControl is DropDownList)
            {
                if (String.IsNullOrEmpty(this.DropDownFirstItem))
                    _listControl.Items.Add(new ListItem(string.Format("-- {0} --", this.Title), EMPTYITEMVALUE));
                else
                    _listControl.Items.Add(new ListItem(string.Format("-- {0} --", this.DropDownFirstItem), EMPTYITEMVALUE));
            }
        }

        private void TraceDebugMessage(string message)
        {
            if (Debug)
            {
                DebugLines.Add(message);
            }
        }

        private void TraceStatus()
        {
            TraceDebugMessage(string.Format("HasFilter: {0}.", HasFilter));
            if (_filterValues == null)
            {
                TraceDebugMessage("No connection found.");
            }
            else
            {
                TraceDebugMessage("Web Part is connected as consumer.");
                if (_filterValues.ParameterValues == null)
                {
                    TraceDebugMessage("No filter values found.");
                }
                else
                {
                    TraceDebugMessage("Web Part is connected as consumer and has values.");
                    TraceDebugMessage(string.Format("Number of filter values: {0}.", _filterValues.ParameterValues.Count));
                }
            }
            if (ItemList == null)
            {
                TraceDebugMessage("List not found.");
            }
            else
            {
                TraceDebugMessage(string.Format("Default view url of the list: {0}.", ItemList.DefaultViewUrl));
                TraceDebugMessage(string.Format("DisplayField: {0}.", DisplayField));
                TraceDebugMessage(string.Format("ValueField: {0}.", ValueField));
                if (ItemList.Fields.ContainsField(DisplayField))
                    TraceDebugMessage("DisplayField found in list.");
                else
                    TraceDebugMessage("DisplayField not found in list.");
                if (ItemList.Fields.ContainsField(ValueField))
                    TraceDebugMessage("ValueField found in list.");
                else
                    TraceDebugMessage("ValueField not found in list.");
                if (_filterValues != null && !string.IsNullOrEmpty(_filterValues.ParameterName))
                {
                    TraceDebugMessage(string.Format("Filter parametername: {0}.", _filterValues.ParameterName));
                    if (ItemList.Fields.ContainsField(_filterValues.ParameterName))
                    {
                        TraceDebugMessage("Filter parametername field found in list.");
                        SPField field = ItemList.Fields[_filterValues.ParameterName];
                        TraceDebugMessage(string.Format("List field: {0} ({1}).", field.InternalName, field.TypeAsString));
                        Field fld = FieldFactory.GetField(field);
                        TraceDebugMessage(string.Format("Field: {0} ({1}).", fld.Name, fld.FieldType.ToString()));
                        if (_filterValues.ParameterValues != null)
                        {
                            TraceDebugMessage(string.Format("CAML where: {0}.", System.Web.HttpUtility.HtmlEncode(ListSupport.GetCAML(ItemList, _filterValues.ParameterName, _filterValues.ParameterValues))));
                        }
                    }
                    else
                    {
                        TraceDebugMessage("Filter parametername field not found in list.");
                    }
                }
            }
        }

        private TagList PopulateTagList()
        {
            try
            {
                if (ItemList == null)
                {
                    return null;
                }
                if (!HasFilter || (_filterValues != null && _filterValues.ParameterValues != null && _filterValues.ParameterValues.Count > 0))
                {
                    List<KeyValuePair<string, string>> items = ListSupport.GetListItems(ItemList, DisplayField, ValueField, _filterValues, ItemLimit);
                    SPField displayField = ItemList.Fields.GetFieldByInternalName(DisplayField);
                    TagList tags = new TagList(Page.Request.Url.ToString());
                    foreach (KeyValuePair<string, string> item in items)
                    {
                        switch (displayField.Type)
                        {
                            case SPFieldType.MultiChoice:
                                string[] values = item.Value.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (string val in values)
                                {
                                    tags.RegisterTag(val, val);
                                }
                                break;
                            case SPFieldType.User:
                                SPFieldUser user = (SPFieldUser)displayField;
                                if (user.AllowMultipleValues)
                                {
                                    string[] lookupvalues = item.Value.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                                    foreach (string val in lookupvalues)
                                    {
                                        tags.RegisterTag(val, val);
                                    }
                                }
                                else
                                {
                                    tags.RegisterTag(item.Value, item.Key);
                                }
                                break;
                            case SPFieldType.Lookup:
                                SPFieldLookup lookup = (SPFieldLookup)displayField;
                                if (lookup.AllowMultipleValues)
                                {
                                    string[] lookupvalues = item.Value.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                                    foreach (string val in lookupvalues)
                                    {
                                        tags.RegisterTag(val, val);
                                    }
                                }
                                else
                                {
                                    tags.RegisterTag(item.Value, item.Key);
                                }
                                break;
                            default:
                                tags.RegisterTag(item.Value, item.Key);
                                break;
                        }
                    }
                    tags.Sort();
                    return tags;
                }
                return null;
            }
            catch (Exception ex)
            {
                _exception = ex;
                return null;
            }
        }

        private bool ConfigurationValid
        {
            get
            {
                return ItemList != null && !string.IsNullOrEmpty(ValueField) && !string.IsNullOrEmpty(DisplayField);
            }
        }

        private void PopulateList()
        {
            try
            {
                TraceStatus();
                if (_listControl == null || !ConfigurationValid)
                    return;
                List<string> selectedValues = new List<string>();
                foreach (ListItem sel in _listControl.Items)
                {
                    if (sel.Selected && sel.Value!=EMPTYITEMVALUE)
                    {
                        selectedValues.Add(sel.Value);
                    }
                }
                if (!HasFilter || (_filterValues != null && _filterValues.ParameterValues != null && _filterValues.ParameterValues.Count > 0))
                {
                    ResetList();

                    List<KeyValuePair<string, string>> items = ListSupport.GetListItems(ItemList, DisplayField, ValueField, _filterValues, ItemLimit);
                    SPField displayField = ItemList.Fields.GetFieldByInternalName(DisplayField);
                    foreach (KeyValuePair<string, string> item in items)
                    {
                        switch (displayField.Type)
                        {
                            case SPFieldType.MultiChoice:
                                string[] values = item.Value.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                                foreach (string val in values)
                                {
                                    AddItem(new ListItem(val));
                                }
                                break;
                            case SPFieldType.User:
                                SPFieldUser user = (SPFieldUser)displayField;
                                if (user.AllowMultipleValues)
                                {
                                    string[] lookupvalues = item.Value.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                                    foreach (string val in lookupvalues)
                                    {
                                        AddItem(new ListItem(val));
                                    }
                                }
                                else
                                {
                                    AddItem(new ListItem(item.Value, item.Key));
                                }
                                break;
                            case SPFieldType.Lookup:
                                SPFieldLookup lookup = (SPFieldLookup)displayField;
                                if (lookup.AllowMultipleValues)
                                {
                                    string[] lookupvalues = item.Value.Split(new string[] { ";#" }, StringSplitOptions.RemoveEmptyEntries);
                                    foreach (string val in lookupvalues)
                                    {
                                        AddItem(new ListItem(val));
                                    }
                                }
                                else
                                {
                                    AddItem(new ListItem(item.Value, item.Key));
                                }
                                break;
                            default:
                                AddItem(new ListItem(item.Value, item.Key));
                                break;
                        }
                    }
                    if (selectedValues.Count > 0)
                    {
                        foreach (string s in selectedValues)
                        {
                            ListItem itm = _listControl.Items.FindByValue(s);
                            if (itm != null)
                            {
                                itm.Selected = true;
                                if (_listControl is DropDownList || _listControl is RadioButtonList)
                                {
                                    break;
                                }
                            }
                        }
                    }
                    else if (_defaultValueProvider != null && !String.IsNullOrEmpty(_defaultValueProvider.DefaultValue))
                    {
                            ListItem itm = _listControl.Items.FindByValue(_defaultValueProvider.DefaultValue);
                            if (itm != null)
                            {
                                itm.Selected = true;
                            }
                    }
                }
            }
            catch (Exception ex)
            {
                _exception = ex;
            }
        }

        private string SaveFilter()
        {
            string result = string.Empty;
            if (_filterValues != null && _filterValues.ParameterValues != null && _filterValues.ParameterValues.Count > 0)
            {
                result += _filterValues.ParameterName;
                foreach (String s in _filterValues.ParameterValues)
                {
                    result += s;
                }
            }
            return result;
        }

        private void AddItem(ListItem itemToAdd)
        {
            if (_distinctValues == null)
            {
            }
            if (!SelectDistinct || !_distinctValues.Contains(itemToAdd.Text))
            {
                _listControl.Items.Add(itemToAdd);
            }
            if (SelectDistinct)
            {
                _distinctValues.Add(itemToAdd.Text);
            }
        }

        SPList ItemList
        {
            get
            {
                if (_list != null)
                {
                    return _list;
                }
                if (string.IsNullOrEmpty(ListUrl) || string.IsNullOrEmpty(DisplayField) || string.IsNullOrEmpty(ValueField) || DisplayField == EMPTYITEMVALUE || ValueField == EMPTYITEMVALUE)
                {
                    return null;
                }
                _list = ListSupport.GetList(ListUrl);
                if (_list == null)
                {
                    return null;
                }
                if (!_list.Fields.ContainsField(DisplayField))
                {
                    return null;
                }
                if (!_list.Fields.ContainsField(ValueField))
                {
                    return null;
                }
                return _list;
            }
        }

        [ConnectionProvider(
        "default value",
        "UniqueIDForDefaultValueConnection",
        AllowsMultipleConnections = true)]
        public Microsoft.SharePoint.WebPartPages.IDefaultFilterValue SetDefaultValueConnection()
        {
            return this;
        }

        [ConnectionProvider(
        "filter value",
        "UniqueIDForFilterValueConnection",
        AllowsMultipleConnections = true)]
        public Microsoft.SharePoint.WebPartPages.ITransformableFilterValues SetFilterConnection()
        {
            return this;
        }

        [ConnectionConsumer(
            "default value",
            "UniqueIDForListItemFilterDefaultValue",
            AllowsMultipleConnections = false)]
        public void SetDefaultFilterValueProvider(Microsoft.SharePoint.WebPartPages.IDefaultFilterValue provider)
        {
            _defaultValueProvider = provider;
            ForceReload();
        }

        [ConnectionConsumer(
            "filter",
            "UniqueIDForListItemFilterConsumer",
            AllowsMultipleConnections = false)]
        public void SetFilter(Microsoft.SharePoint.WebPartPages.IFilterValues filterValues)
        {
            _filterValues = filterValues;
            HasFilter = filterValues != null;

            SPList list = ListSupport.GetList(ListUrl);
            if (list !=null && filterValues != null)
            {
                EnsureChildControls();
                List<Microsoft.SharePoint.WebPartPages.ConsumerParameter> parameters = new List<Microsoft.SharePoint.WebPartPages.ConsumerParameter>();
                foreach (SPField field in list.Fields)
                {
                    if (!field.Hidden)
                    {
                        parameters.Add(new Microsoft.SharePoint.WebPartPages.ConsumerParameter(
                            field.Title,
                            Microsoft.SharePoint.WebPartPages.ConsumerParameterCapabilities.SupportsEmptyValue |
                            Microsoft.SharePoint.WebPartPages.ConsumerParameterCapabilities.SupportsSingleValue |
                            Microsoft.SharePoint.WebPartPages.ConsumerParameterCapabilities.SupportsMultipleValues |
                            Microsoft.SharePoint.WebPartPages.ConsumerParameterCapabilities.SupportsAllValue));
                    }
                }
                filterValues.SetConsumerParameters(new System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.SharePoint.WebPartPages.ConsumerParameter>(parameters));
                //if (!string.IsNullOrEmpty(filterValues.ParameterName) && filterValues.ParameterValues != null && filterValues.ParameterValues.Count > 0)
                if (string.IsNullOrEmpty(filterValues.ParameterName) || filterValues.ParameterValues == null || filterValues.ParameterValues.Count == 0)
                {
                    ResetList();
                }
                // Generate a new filter identification string.
                string newFilter = SaveFilter();

                // If filter has changed, force a reload.
                if (newFilter != PreviousFilterAsText)
                {
                    ForceReload();
                }
            }
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            if (Debug && _debugLines!=null && _debugLines.Count > 0)
            {
                writer.WriteLine("=== DEBUG INFORMATION ===<br>");
                foreach (string line in _debugLines)
                {
                    writer.WriteLine(string.Format("{0}<br>", line));
                }
            }

            base.RenderContents(writer);

            if (string.IsNullOrEmpty(ListUrl) || string.IsNullOrEmpty(DisplayField) || string.IsNullOrEmpty(ValueField) || DisplayField == EMPTYITEMVALUE || ValueField == EMPTYITEMVALUE)
            {
                writer.WriteLine(BaseDataWebPart.GetOpenToolPaneText("This webpart is not yet configured", this.ID));
            }
            try
            {
                switch (DisplayMode)
                {
                    case 3: // Tag cloud
                        RenderTagcloud(writer);
                        break;
                    case 4: // Xslt transformation
                        if (!string.IsNullOrEmpty(XsltStyleSheet))
                        {
                            RenderXsltTransformation(writer);
                        }
                        else
                        {
                            throw new Exception("Select a XSLT stylesheet in the web part properties.");
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                _exception = ex;
            }

            // Error handling
            if (_exception != null)
            {
                writer.WriteLine(string.Format("Error: {0}", _exception.Message));
            }
        }

        private void RenderTagcloud(HtmlTextWriter writer)
        {
            // Tag Cloud based on the tag cloud web part in the Community Kit for SharePoint
            // http://www.codeplex.com/CKS
            TagList tags = CurrentTagList;
            if (tags == null)
                return;
            HtmlGenericControl tagCloudDiv = new HtmlGenericControl("div");
            tagCloudDiv.Attributes.Add("id", "tagCloud");
            this.Controls.Add(tagCloudDiv);

            if (ShowAllInTagCloud)
            {
                Tag allTag = new Tag(SHOWALLITEMTEXT, 1, SHOWALLITEM);
                RenderTag(tagCloudDiv, tags, allTag, true);
            }

            foreach (Tag tag in tags.Tags)
            {
                RenderTag(tagCloudDiv, tags, tag, false);
            }
            tagCloudDiv.RenderControl(writer);
        }

        private void RenderTag(HtmlGenericControl tagCloudDiv, TagList tags, Tag tag, Boolean useTagValue)
        {
            this.HorizontalAlign = HorizontalAlign.Right;
            HtmlAnchor a = new HtmlAnchor();
            String txt = tag.Name;
            if (useTagValue)
                txt = tag.Value;
            a.HRef = string.Format("{0}?{2}={1}", tags.PageUrl, SPEncode.UrlEncode(txt), QueryStringTag);
            if (Page.Request.QueryString.Count > 0)
            {
                StringBuilder prevQuery = new StringBuilder();
                NameValueCollection previous = new NameValueCollection(Page.Request.QueryString);
                previous.Remove(QueryStringTag);
                foreach (String name in previous)
                {
                    prevQuery.AppendFormat("{0}={1}", name, previous[name]);
                }
                if (!String.IsNullOrEmpty(prevQuery.ToString()))
                {
                    a.HRef += String.Format("&{0}", prevQuery.ToString());
                }
            }
            a.Title = tag.Count.ToString() + " records";
            a.InnerText = tag.Name;

            int weight = TagHelper.GetTagWeight(tag.Count, tags.MaxCount);
            if (weight > 0)
            {
                if (!string.IsNullOrEmpty(ControlCssClass))
                {
                    a.Attributes["class"] = this.ControlCssClass + weight.ToString();
                }
                a.Style.Add(HtmlTextWriterStyle.FontSize, fontSizes[weight - 1]);
                tagCloudDiv.Controls.Add(a);

                // adding some spaces between tags
                LiteralControl lc = new LiteralControl("  ");
                tagCloudDiv.Controls.Add(lc);
            }
        }

        private void RenderXsltTransformation(HtmlTextWriter writer)
        {
            // Get the url for the stylesheet
            if (!File.Exists(ResourcePath + XsltStyleSheet))
            {
                throw new Exception(string.Format("XSLT File not found: {0}.", ResourcePath + XsltStyleSheet));
            }
            FileStream xsltStream = new FileStream(ResourcePath + XsltStyleSheet, FileMode.Open);
            try
            {
                XmlReader xsltReader = XmlReader.Create(xsltStream);

                MemoryStream xml = WriteXml();
                XmlReader xmlReader = XmlReader.Create(xml);

                try
                {
                    System.Xml.Xsl.XslCompiledTransform xslTransform = new XslCompiledTransform(false);
                    xslTransform.Load(xsltReader);
                    using (TextWriter stringWriter = new StringWriter())
                    {
                        xslTransform.Transform(xmlReader, null, stringWriter);
                        writer.Write(stringWriter.ToString());
                    }
                }
                finally
                {
                    xsltStream.Close();
                    xsltStream.Dispose();
                    xmlReader.Close();
                    xsltReader.Close();
                }
            }
            finally
            {
                xsltStream.Close();
                xsltStream.Dispose();
            }
        }

        public MemoryStream WriteXml()
        {
            // Get the tags for the tagcloud and write them to XML.
            TagList tags = CurrentTagList;
            MemoryStream xmlStream = new MemoryStream();
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            using (XmlWriter writer = XmlWriter.Create(xmlStream, settings))
            {
                writer.WriteStartDocument();
                writer.WriteStartElement("filters");
                if (tags != null)
                {
                    writer.WriteAttributeString("pageurl", tags.PageUrl);
                    foreach (Tag tag in tags.Tags)
                    {
                        writer.WriteStartElement("filter");
                        writer.WriteAttributeString("name", tag.Name);
                        writer.WriteAttributeString("value", SPEncode.UrlEncode(tag.Value));
                        writer.WriteAttributeString("count", tag.Count.ToString());
                        writer.WriteEndElement();
                    }
                }
                writer.WriteFullEndElement();

            }
            xmlStream.Position = 0;
            return xmlStream;//sb.ToString();
        }

        private static string UTF8ByteArrayToString(byte[] p)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            string result = encoding.GetString(p);
            return result;
        }

        #region IWebEditable Members

        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            List<EditorPart> editors = new List<EditorPart>();

            // Add the base editor parts
            EditorPartCollection baseParts = base.CreateEditorParts();
            foreach (EditorPart basePart in baseParts)
                editors.Add(basePart);

            editors.Add(new ListSelectEditorPart(this.ID));
            return new EditorPartCollection(editors);
        }

        object IWebEditable.WebBrowsableObject
        {
            get { return this; }
        }

        #endregion

        #region ITransformableFilterValues Members

        public bool AllowAllValue
        {
            get { return false; }
        }

        public bool AllowEmptyValue
        {
            get { return false; }
        }

        public bool AllowMultipleValues
        {
            get { return true; }
        }

        public string ParameterName
        {
            get { return "FilterValue"; }
        }

        public System.Collections.ObjectModel.ReadOnlyCollection<string> ParameterValues
        {
            get
            {
                List<string> values = new List<string>();
                if (_listControl != null)
                {
                    foreach (ListItem item in _listControl.Items)
                    {
                        if (item.Selected && item.Value != EMPTYITEMVALUE)
                        {
                            values.Add(item.Value);
                        }
                    }
                }
                else if ((DisplayMode == 3 || DisplayMode == 4))
                {
                    if (Page.Request.QueryString[QueryStringTag] != null && !string.IsNullOrEmpty(Page.Request.QueryString[QueryStringTag]))
                    {
                        if (Page.Request.QueryString[QueryStringTag] != SHOWALLITEM)
                        {
                            values.Add(SPEncode.UrlDecodeAsUrl(Page.Request.QueryString[QueryStringTag]));
                        }
                    }
                    else if (_defaultValueProvider != null && !String.IsNullOrEmpty(_defaultValueProvider.DefaultValue))
                    {
                        if (Page.Request.QueryString[QueryStringTag] != SHOWALLITEM)
                        {
                            values.Add(SPEncode.UrlDecodeAsUrl(_defaultValueProvider.DefaultValue));
                        }
                    }
                }
                System.Collections.ObjectModel.ReadOnlyCollection<string> result = new System.Collections.ObjectModel.ReadOnlyCollection<string>(values);
                return result;
            }
        }

        private String QueryStringTag
        {
            get
            {
                String title = Regex.Replace(this.Title, @"\s", String.Empty);
                return String.Format("tag_{0}", SPEncode.HtmlEncode(title));
            }
        }

        #endregion

        #region IDefaultFilterValue Members

        public string DefaultValue
        {
            get
            {
                if (_listControl != null)
                {
                    foreach (ListItem item in _listControl.Items)
                    {
                        if (item.Selected)
                        {
                            return item.Value;
                        }
                    }
                }
                else if ((DisplayMode == 3 || DisplayMode == 4) && Page.Request.QueryString[QueryStringTag] != null && !string.IsNullOrEmpty(Page.Request.QueryString[QueryStringTag]))
                {
                    if (Page.Request.QueryString[QueryStringTag] != SHOWALLITEM)
                    {
                        return SPEncode.UrlDecodeAsUrl(Page.Request.QueryString[QueryStringTag]);
                    }
                }
                return null;
            }
        }

        #endregion
    }
}
